package online.zhangwenzhe.common.security.Impl;

import online.zhangwenzhe.common.security.AuthorityVerifier;
import online.zhangwenzhe.common.security.datasource.AuthenticationService;
import online.zhangwenzhe.common.security.datasource.ResourceRoleMapVo;
import online.zhangwenzhe.common.security.datasource.ResourceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.ArrayList;
import java.util.List;

/**
 * 说明：
 *
 * @author 张文哲
 * @version 1.0.0
 * @since 2018/7/3 16:23
 */

@Component
public class AuthorityVerifierImpl implements AuthorityVerifier {
    @Autowired
    AuthenticationService authenticationService;

    @Override
    public boolean verify(long userid, String uri, String httpMethod) {
        // 获取用户的可访问资源列表
        List<ResourceVo> grantedResource = authenticationService.getGrantedResource(userid);
        // todo: 需要设计缓存

        if (matchResource(uri, httpMethod, grantedResource)) {
            return true;
        }

        return false;
    }

    @Override
    public boolean allowAnonymous(String uri, String httpMethod) {
        // 全部配置好的资源
        List<ResourceVo> allResource = authenticationService.getAllResource();
        // todo: 需要设计缓存


        // uri在已经配置的资源列表中，包含通配符下，说明此资源不允许匿名访问
        if (matchResource(uri, httpMethod, allResource)) {
            return false;
        }

        // 配置好的资源列表没有uri，说明可以匿名访问
        return true;
    }

    private boolean matchResource(String uri, String httpMethod, List<ResourceVo> grantedResource) {
        PathMatcher urlMatcher = new AntPathMatcher();
        ((AntPathMatcher) urlMatcher).setCaseSensitive(false);

        for (ResourceVo resource : grantedResource) {
            if (urlMatcher.match(resource.getUri(), uri)) {
                // todo: 有个问题，可能以后还是不要支持通配符对下级目录支持了，会和参数混合
                //  比如/user/*，可以匹配/user/list，也可以匹配/user/1

                // 通配符情况不考虑请求方式
                if (resource.getUri().contains("*")) {
                    return true;
                }

                // 没有通配符，需要请求方式完全一致
                if (httpMethod.equals(resource.getMethod().toUpperCase())) {
                    return true;
                }
            }
        }
        return false;
    }
}
